#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Datetime: 2019/10/25 13:14
# @Author  : CHEN Wang
# @Site    :
# @File    : fund_info.py
# @Software: PyCharm

"""
脚本说明: 获取基金，基金经理，基金公司相关的基础信息
"""

import pandas as pd
from quant_researcher.quant.project_tool.celebrity import get_lst_condition
from quant_researcher.quant.project_tool import time_tool
from quant_researcher.quant.project_tool.db_operator import my_mysql, db_conn
from quant_researcher.quant.project_tool.logger.my_logger import LOG
from quant_researcher.quant.datasource_fetch.fund_api import fund_classification
from quant_researcher.quant.datasource_fetch.common_data_api.common_tools import get_max_date_of_table
from quant_researcher.quant.datasource_fetch.fund_api.fund_holding_related import get_holding_report_info

T_FUND_INFO = 'mf_bd_fndinfo'
C_ESTABLISH_DATE = 'establish_date'  # 成立日期
C_END_DATE = 'fund_enddate'  # 终止日期
C_C = 'fund_code'
C_S_NAME = 'fund_sname'
C_MGR_CPY_C = 'mgrcomp_code'

T_FUND_CHARGE_RATE = 'mf_bd_chargerate'

T_MANAGER_FUND = 'mf_bd_fndmgr_servinfo'
C_M_START = 'serving_date'
C_M_END = 'resign_date'
M_C = 'manager_code'

T_MANAGER_INFO = 'mf_bd_fndmanager'
C_E_Y = 'entry_year'  # 证券从业年份

T_FUND_BENCHMARK = 'mf_di_fndbenchmark'
C_B = 'benchmark'
C_E_D = 'end_date'

T_MANAGER_BENCHMARK = 'mf_di_mgrbenchmark'
C_F_T = 'fund_type'  # 管理基金类型

T_COMPANY_BENCHMARK = 'mf_di_compbenchmark'

T_FUND_NET_VALUE = 'mf_nv_netvalue'

T_COMPANY_INFO = 'mf_bd_fndmgrcomp'


def get_fund_basic_info(fund_code, select=None, **kwargs):
    """
    获得基金的基本信息， todo 有没有历史界面数据

    :param str or list or None fund_code: 基金代码，支持str（单基金）、list（单基金或多基金）、None（全部基金）
    :param list select: 需要获取哪些基本信息
    :return: pd.DataFrame
                - fund_code: 基金代码
                - fund_backcode: 基金后端申购代码
                - master_code: 基金主代码
                - fund_sname: 基金简称
                - issue_start_date: 基金发行日期
                - establish_date_earliest: 基金最早的成立日期
                - establish_date: 基金成立日期/生效日期（转型基金的转型日期）
                - inception_shares: 基金成立初规模（份）
                - fund_managers: 基金经理列表
                - mgrcomp_code: 基金管理人编码
                - trustee_code: 基金托管人编码
                - operation_way: 基金运作方式，6030=封闭式、6031=创新封闭式、6020=普通开放式、6021=创新开放式、
                                 6022=LOF、6023=ETF、6024=FOF、6025=ETF联接基金、6040=其他
                - compare_benchmark: 业绩比较基准
                - track_target: 基金跟踪标的
                - trade_mode: 交易方式，1=场外交易；2=场内交易; 3=场内场外交易
                - operation_phase: 运行阶段，1010-核准发行/即将发售,1011-认购期（募集期）、1012-建仓期（封闭期）、
                                   1013-运行期、1014-清算期、1015=终止、1016=发行失败
                - fund_state: 基金状态，0正常，-1=停止运作
                - fund_enddate: 基金终止日期
                - is_initiating: 是否发起式，0=否，1=是
                - is_fof: 是否FOF基金，0=否，1=是
                - is_pensiontg: 是否目标养老，0=否，1=是
    """
    conn = kwargs.pop('conn', None)
    tmp_conn = db_conn.get_basic_data_conn() if conn is None else conn

    where = []
    if isinstance(fund_code, str):
        where.append(f'fund_code=\'{fund_code}\'')
    elif isinstance(fund_code, list):
        where.append(get_lst_condition(fund_code, 'fund_code'))
    elif fund_code is None:
        pass
    else:
        LOG.error('目前fund_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    if select is None:
        select = ['fund_code', 'fund_backcode', 'master_code', 'fund_sname', 'issue_start_date',
                  'establish_date_earliest', 'establish_date', 'inception_shares', 'fund_managers',
                  'mgrcomp_code', 'trustee_code', 'operation_way', 'compare_benchmark', 'track_target',
                  'trade_mode', 'operation_phase', 'fund_state', 'fund_enddate', 'is_initiating', 'is_fof',
                  'is_pensiontg']

    df = my_mysql.read_v2(
        select=select, where=where, sfrom=T_FUND_INFO, conn=tmp_conn
    )
    if conn is None:
        tmp_conn.close()

    if df.empty:
        LOG.error(f"没有找到{fund_code}的信息，请检查输入")
        return

    return df


def get_fund_charge_rate(fund_code, charge_type=None, charge_mode=None):
    """
    得到基金的费率信息

    :param str or list or None fund_code: 基金代码，支持str、list、None
    :param str charge_type: 费率类别，1100-认购费率，1200-申购费率，1300-赎回费率，1400-转换费率，
                            2001-管理费，2002-托管费，2003-销售服务费
    :param str charge_mode: 收费模式，10-前端收费模式，20-后端收费模式
    :return: pd.DataFrame
                - fund_code: 基金代码
                - chgrate_type: 费率类别
                - charge_mode: 收费模式
                - execute_date: 执行日期
                - currency: 币种
                - chgrate_lval: 费率收取最低值
                - chgrate_tval: 费率收取最高值
                - chgrate_unit: 费率值单位
                - chgrate_csymbol: 费率值比较符号
    """
    conn = db_conn.get_basic_data_conn()
    where = []
    if isinstance(fund_code, str):
        where.append(f'fund_code=\'{fund_code}\'')
    elif isinstance(fund_code, list):
        where.append(get_lst_condition(fund_code, 'fund_code'))
    elif fund_code is None:
        pass
    else:
        LOG.error('目前fund_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError
    if charge_type is not None:
        where.append(f"chgrate_type = '{charge_type}'")
    if charge_mode is not None:
        where.append(f"charge_mode = '{charge_mode}'")

    select = ['fund_code', 'chgrate_type', 'charge_mode', 'execute_date', 'currency', 'chgrate_lval',
              'chgrate_tval', 'chgrate_unit', 'chgrate_csymbol']

    df = my_mysql.read_v2(
        select=select, where=where, sfrom=T_FUND_CHARGE_RATE, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{fund_code}的信息，请检查输入")
        return

    return df


def get_all_fund_code(end_date=None, **kwargs):
    """
    获取end_date时点存续的所有基金代码

    :param str end_date: 如'2020-10-30'，默认为None, 则获取历史存在过的所有基金
    :return: list
    """
    conn = kwargs.pop('conn', None)
    tmp_conn = db_conn.get_basic_data_conn() if conn is None else conn

    if end_date is None:
        fund_code_df = my_mysql.read_v2(select='distinct fund_code',
                                        sfrom=T_FUND_INFO,
                                        conn=tmp_conn)
    else:
        fund_code_df = my_mysql.read_v2(select='distinct fund_code',
                                        sfrom=T_FUND_INFO,
                                        where=['fund_enddate is null',
                                               f"fund_enddate >= '{end_date.replace('-', '')}'"],
                                        conn=tmp_conn, where_and=False)
    if conn is None:
        tmp_conn.close()

    if fund_code_df.empty:
        LOG.error(f"没有找到基金的信息，请检查输入{T_FUND_INFO}表")
        return
    fund_code_list = fund_code_df['fund_code'].tolist()
    return fund_code_list


def get_all_manager_code():
    """
    得到所有基金经理的代码

    :return: list
    """
    conn = db_conn.get_basic_data_conn()
    select = f'distinct manager_code'
    df = my_mysql.read_v2(sfrom=T_MANAGER_INFO, select=select, conn=conn)
    conn.close()
    ans = list(df['manager_code'].values)
    return ans


def get_all_company_code():
    """
    获得所有基金公司的代码

    :return: list
    """
    conn = db_conn.get_basic_data_conn()
    select = f'distinct mgrcomp_code'
    df = my_mysql.read_v2(sfrom=T_FUND_INFO, select=select,
                          conn=conn)
    conn.close()
    ans = list(df['mgrcomp_code'].values)
    return ans


def get_fund_sname(fund_code=None):
    """
    获取基金简称

    :param str or list or None fund_code: 基金代码，支持str、list、None
    :return: pd.DataFrame
                - fund_code: 基金代码
                - fund_sname: 基金简称
    """
    conn = db_conn.get_basic_data_conn()
    where = []
    if isinstance(fund_code, str):
        where.append(f'fund_code=\'{fund_code}\'')
    elif isinstance(fund_code, list):
        where.append(get_lst_condition(fund_code, 'fund_code'))
    elif fund_code is None:
        pass
    else:
        LOG.error('目前fund_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        select=['fund_code', 'fund_sname'], where=where, sfrom=T_FUND_INFO, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{fund_code}的基金名称，请检查输入")
        return

    return df


def get_manager_name(manager_code=None):
    """
    获取基金经理姓名

    :param str or list or None manager_code: 基金代码，支持str、list、None
    :return: pd.DataFrame
                - manager_code: 基金经理代码
                - manager_name: 基金经理名称
    """
    conn = db_conn.get_basic_data_conn()
    where = []
    if isinstance(manager_code, str):
        where.append(f'manager_code=\'{manager_code}\'')
    elif isinstance(manager_code, list):
        where.append(get_lst_condition(manager_code, 'manager_code'))
    elif manager_code is None:
        pass
    else:
        LOG.error('目前manager_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        select=['manager_code', 'manager_name'], where=where, sfrom=T_MANAGER_INFO, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{manager_code}的基金经理名称，请检查输入")
        return

    return df


def get_company_code_by_name(company_name):
    """
    根据基金公司的名称查询基金公司代码

    :param str or list or None company_name: 基金公司简称，如"安信基金"
    :return: pd.DataFrame
    """
    conn = db_conn.get_basic_data_conn()
    where = []
    if isinstance(company_name, str):
        where.append(f'mgrcomp_sname=\'{company_name}\'')
    elif isinstance(company_name, list):
        where.append(get_lst_condition(company_name, 'mgrcomp_sname'))
    elif company_name is None:
        pass
    else:
        LOG.error('目前company_name只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        select=['mgrcomp_code as company_code', 'mgrcomp_sname as company_name'], where=where,
        sfrom=T_COMPANY_INFO, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{company_name}的基金公司代码，请检查输入")
        return

    return df


def get_fund_net_asset(fund_code=None, start_date=None, end_date=None, only_latest=True, **kwargs):
    """
    获取基金净资产规模数据

    :param str or list or None fund_code: 基金代码，支持单个（str）、多个（list）、所有（None）
    :param str or int or datetime.date or datetime.datetime or int start_date: 开始时间，支持带杠字符串、不带杠字符串、datetime、date、int格式
    :param str or int or datetime.date or datetime.datetime or int end_date: 结束时间，支持带杠字符串、不带杠字符串、datetime、date、int格式
    :param bool only_latest: 是否只获取最新, 默认为True
    :return: pd.DataFrame
    """
    conn = kwargs.pop('conn', None)
    tmp_conn = db_conn.get_basic_data_conn() if conn is None else conn

    df = get_holding_report_info(
        report='financial', fund_code=fund_code, only_latest=only_latest,
        report_type=[1, 2, 3, 4], start_date=start_date, end_date=end_date,
        select=['fund_code', 'report_date', 'net_asset'], conn=tmp_conn)

    if conn is None:
        tmp_conn.close()
    return df


def get_manager_serve_info(asset_type='manager', asset_code=None):
    """
    得到基金经理的任职信息，支持通过基金经理代码查询和通过基金代码查询

    :param str asset_type: manager-基金经理，fund-基金
    :param str or list or None asset_code: 支持单个(str)、多个(list)、所有(None)
    :return: pd.DataFrame
                - manager_code: 基金经理代码
                - fund_code: 基金代码
                - serving_date: 任职开始时间
                - resign_date: 离职时间
                - isposition: 是否在任，1是，0否
    """
    conn = db_conn.get_basic_data_conn()

    if asset_type == 'manager':
        asset_name = 'manager_code'
    elif asset_type == 'fund':
        asset_name = 'fund_code'
    else:
        LOG.error(f"目前asset_type参数只支持manager和fund，请重新输入")
        return

    select = ['manager_code', 'fund_code', 'serving_date', 'resign_date', 'isposition']
    where = ['post=\'004\'']  # post 为 004，表示在该基金中任职基金经理，不是其他角色，分析师或助理之类
    if isinstance(asset_code, str):
        where.append(f"{asset_name}='{asset_code}'")
    elif isinstance(asset_code, list):
        where.append(get_lst_condition(asset_code, asset_name))
    elif asset_code is None:
        pass
    else:
        LOG.error('目前asset_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        sfrom=T_MANAGER_FUND, select=select, where=where, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{asset_type}类型{asset_code}代码的信息，请检查")
        return

    return df


def get_company_fund_relation(asset_type='company', asset_code=None):
    """
    得到基金公司和基金的对应关系，支持通过基金公司代码查询和通过基金代码查询

    :param str asset_type: company-基金公司，fund-基金
    :param str or list or None asset_code: 支持单个(str)、多个(list)、所有(None)
    :return: pd.DataFrame
                - company_code: 基金公司代码
                - fund_code: 基金代码
    """
    conn = db_conn.get_basic_data_conn()

    if asset_type == 'company':
        asset_name = 'mgrcomp_code'
    elif asset_type == 'fund':
        asset_name = 'fund_code'
    else:
        LOG.error(f"目前asset_type参数只支持company和fund，请重新输入")
        return

    select = ['mgrcomp_code as company_code', 'fund_code']
    where = []
    if isinstance(asset_code, str):
        where.append(f"{asset_name}='{asset_code}'")
    elif isinstance(asset_code, list):
        where.append(get_lst_condition(asset_code, asset_name))
    elif asset_code is None:
        pass
    else:
        LOG.error('目前asset_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        sfrom=T_FUND_INFO, select=select, where=where, conn=conn
    )
    conn.close()

    if df.empty:
        LOG.error(f"没有找到{asset_type}类型{asset_code}代码的信息，请检查")
        return

    return df


def get_fund_benchmark(fund_code=None, **kwargs):
    """
    得到基金的业绩比较基准

    :param str or list or None fund_code: 基金代码，支持单个基金(str)、基金列表(list)、所有基金(None)
    :param kwargs:
            - list select: 需要哪几列，默认fund_code和benchmark
            - str or list or None fund_type_1: 需要哪些基金类型（一级分类）
            - bool convert_2_list: 是否将结果转换成list
    :return: pd.DataFrame
                - fund_code: 基金代码
                - benchmark: 截止日期
                - calendar_type: 业绩基准指数代码
                - fund_type_1: 基金一级分类代码
                - fund_type_2: 基金二级分类代码
    """
    select = kwargs.pop('select', None)
    fund_type_1 = kwargs.pop('fund_type_1', None)
    convert_2_list = kwargs.pop('convert_2_list', False)

    conn = db_conn.get_derivative_data_conn()
    if select is None:
        select = ['fund_code', 'benchmark']
    where = [f"end_date='{get_max_date_of_table('end_date', T_FUND_BENCHMARK)}'"]

    if isinstance(fund_code, str):
        where.append(f'fund_code=\'{fund_code}\'')
    elif isinstance(fund_code, list):
        where.append(get_lst_condition(fund_code, 'fund_code'))
    elif fund_code is None:
        pass
    else:
        LOG.error('目前fund_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    if isinstance(fund_type_1, str):
        where.append(f'fund_type_1=\'{fund_type_1}\'')
    elif isinstance(fund_type_1, list):
        where.append(get_lst_condition(fund_type_1, 'fund_type_1'))
    elif fund_type_1 is None:
        pass
    else:
        LOG.error('目前fund_type_1只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    df = my_mysql.read_v2(
        select=select, where=where, sfrom=T_FUND_BENCHMARK, conn=conn
    )
    conn.close()
    if df.empty:
        LOG.error(f"没有找到{fund_code}的信息，请检查输入")
        return

    if convert_2_list:
        df = [x[0] if len(select) == 1 else tuple(x) for x in df.values]

    return df


def get_manager_benchmark(manager_code=None, **kwargs):
    """
    得到基金经理的业绩比较基准

    :param manager_code: 基金经理代码，支持单个基金经理(str)、基金经理列表(list)、所有基金经理(None)
    :param kwargs:
            - select: 需要哪几列，默认manager_code、fund_type、benchmark
            - fund_type: 需要哪些基金类型
            - convert_2_list: 将结果转换成list
    :return:
    """
    select = kwargs.pop('select', None)
    fund_type = kwargs.pop('fund_type', None)
    convert_2_list = kwargs.pop('convert_2_list', False)

    conn = db_conn.get_derivative_data_conn()
    if select is None:
        select = ['manager_code', 'fund_type', 'benchmark']

    where = []
    if isinstance(manager_code, str):
        where.append(f'manager_code=\'{manager_code}\'')
    elif isinstance(manager_code, list):
        where.append(get_lst_condition(manager_code, 'manager_code'))
    elif manager_code is None:
        pass
    else:
        LOG.error('目前manager_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    if isinstance(fund_type, str):
        where.append(f'fund_type=\'{fund_type}\'')
    elif isinstance(fund_type, list):
        where.append(get_lst_condition(fund_type, 'fund_type'))
    elif fund_type is None:
        pass
    else:
        LOG.error('目前fund_type只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    where.append(f"end_date='{get_max_date_of_table('end_date', T_MANAGER_BENCHMARK)}'")

    df = my_mysql.read_v2(
        sfrom=T_MANAGER_BENCHMARK, select=select, where=where, conn=conn
    )

    if df.empty:
        LOG.error(f"没有找到{manager_code}的信息，请检查输入")
        return

    if convert_2_list:
        df = [x[0] if len(select) == 1 else tuple(x) for x in df.values]

    return df


def get_company_benchmark(company_code=None, **kwargs):
    """
    得到基金公司的业绩比较基准

    :param company_code: 基金公司代码，支持单个(str)、多个(list)、所有(None)
    :param kwargs:
            - select: 需要哪几列，默认company_code、fund_type、benchmark
            - fund_type: 需要哪些基金类型
            - convert_2_list: 将结果转换成list
    :return:
    """
    select = kwargs.pop('select', None)
    fund_type = kwargs.pop('fund_type', None)
    convert_2_list = kwargs.pop('convert_2_list', False)

    conn = db_conn.get_derivative_data_conn()
    if select is None:
        select = ['company_code', 'fund_type', 'benchmark']

    where = []
    if isinstance(company_code, str):
        where.append(f'company_code=\'{company_code}\'')
    elif isinstance(company_code, list):
        where.append(get_lst_condition(company_code, 'company_code'))
    elif company_code is None:
        pass
    else:
        LOG.error('目前company_code只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    if isinstance(fund_type, str):
        where.append(f'fund_type=\'{fund_type}\'')
    elif isinstance(fund_type, list):
        where.append(get_lst_condition(fund_type, 'fund_type'))
    elif fund_type is None:
        pass
    else:
        LOG.error('目前fund_type只支持str、list或者None，请按要求输入')
        raise NotImplementedError

    where.append(f"end_date='{get_max_date_of_table('end_date', T_COMPANY_BENCHMARK)}'")

    df = my_mysql.read_v2(
        sfrom=T_COMPANY_BENCHMARK, select=select, where=where, conn=conn
    )

    if df.empty:
        LOG.error(f"没有找到{company_code}的信息，请检查输入")
        return

    if convert_2_list:
        df = [x[0] if len(select) == 1 else tuple(x) for x in df.values]

    return df


def get_fund_or_manager_inception_date(asset_type, asset_code, fund_type='00'):
    """
    得到基金的成立日期，以及净值开始日期，这两个日期可能不相同。或者基金经理管理某一类型基金的开始任职日期和净值开始日期

    :param str asset_type: fund(基金)或manager(基金经理)
    :param str asset_code: 基金或基金经理代码
    :param str fund_type: 基金经理管理基金类型，基金一级分类，如果是'00'表示包括所有的类型
    :return: tuple, (establish_date, nav_start_date)，格式为带-字符串，('2010-08-20', '2010-09-01')
    """
    conn = db_conn.get_basic_data_conn()
    if asset_type == 'fund':
        establish_date = pd.read_sql(f"select establish_date "
                                     f"from {T_FUND_INFO} "
                                     f"where fund_code = '{asset_code}' ", conn)
        if establish_date.empty:
            LOG.error(f"没有找到基金{asset_code}的相关信息，请检查基金代码是否输入正确")
            conn.close()
            return None, None
        establish_date = establish_date.iloc[0, 0]
    elif asset_type == 'manager':
        mgr_fund_df = get_manager_serve_info(asset_type='manager', asset_code=asset_code)
        cls_1_df = fund_classification.get_fund_cls_info(
            category_rank=1, select=['fund_code', 'category_code as `type_1`']
        )
        mgr_fund_df = mgr_fund_df.merge(cls_1_df, how='left', on='fund_code')
        if fund_type != '00':
            mgr_fund_df = mgr_fund_df[mgr_fund_df['type_1'] == fund_type]

        if mgr_fund_df.empty:
            LOG.error(f"没有找到基金经理{asset_code}管理的{fund_type}类型的基金信息，请检查基金经理代码是否正确")
            conn.close()
            return None, None
        mgr_fund_df = mgr_fund_df.sort_values(by='serving_date')
        asset_code = mgr_fund_df['fund_code'].iloc[0]
        establish_date = mgr_fund_df['serving_date'].iloc[0]
    else:
        LOG.error("input_type只支持fund、manager，请重新输入")
        conn.close()
        raise NotImplementedError
    if establish_date is None:
        LOG.error(f"找到基金{asset_code}的信息，但其成立时间为空，请检查原因")
        conn.close()
        return None, None
    if asset_type == 'fund':
        establish_date = time_tool.format_date_str(establish_date, '%Y-%m-%d')
    else:
        establish_date = str(establish_date)

    # 有些基金转型了，establish_date是转型日期，找净值开始日期时需要加上end_date的限制条件
    nav_start_date = my_mysql.read_v2(select='min(end_date)', sfrom=T_FUND_NET_VALUE,
                                      where=[f"fund_code = '{asset_code}'",
                                             f"end_date >= '{establish_date}'"],
                                      conn=conn)
    nav_start_date = nav_start_date.iloc[0, 0]
    if nav_start_date is None:
        LOG.warning(f"基金{asset_code}的成立日期为{establish_date}，但没有找到净值信息，"
                    f"可能是新发基金，请做进一步检查")
    else:
        nav_start_date = str(nav_start_date)
    conn.close()

    return establish_date, nav_start_date


if __name__ == '__main__':
    # 测试get_fund_basic_info
    # test = get_fund_basic_info(fund_code='110011')

    # 测试get_fund_charge_rate
    # test = get_fund_charge_rate(fund_code='110011')
    # aaa = get_company_benchmark()
    # bbb = get_fund_net_asset(['110022', '003095'], '2020-06-30', '2020-09-30', False)
    # ccc = get_manager_serve_info('fund', ['110022', '003095'])
    # ddd = get_company_fund_relation('company')
    eee = get_company_code_by_name(['安信基金', '博时基金'])
